﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Betfairer
{
    public class Utils
    {
        /// <summary>
        /// Returns how many milliseconds have passed since 01.01.1970 before current UTC time.
        /// </summary>
        public static long Now
        {
            get
            {
                return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds;
            }
        }

        /// <summary>
        /// Calculates the difference (or the delta) between the two tables.
        /// </summary>
        /// <param name="fst">The first table.</param>
        /// <param name="scnd">The second table.</param>
        /// <returns>Delta-table.</returns>
        //public static Table FindDelta(Table fst, Table scnd)
        //{
        //    Table result = new Table(fst.Hight, fst.Width);

        //    for (int i = 0; i < fst.Hight; ++i)
        //    {
        //        for (int j = 0; j < fst.Width; ++j)
        //        {
        //            result.Set(new Cell(fst.Get(i, j).Coefficient - scnd.Get(i, j).Coefficient, fst.Get(i, j).Amount - scnd.Get(i, j).Amount), i, j);
        //        }
        //    }

        //    return result;
        //}

        /// <summary>
        /// Says whether table is full.
        /// </summary>
        /// <param name="table">Table to check.</param>
        /// <returns>True or false.</returns>
        public static bool Full(Table table)
        {
            int temp = table.Hight;

            for (int i = 0; i < table.Hight; ++i)
            {
                for (int j = 0; j < table.Width - 1; ++j)
                {
                    decimal difference = table.Get(i, j + 1).Coefficient - table.Get(i, j).Coefficient;

                    if (difference > GetStep(table.Get(i, j).Coefficient))
                    {
                        temp--;
                        break;
                    }
                }
            }

            return temp >= table.Hight - 1;
        }

        /// <summary>
        /// Calculates the step for the given coefficient.
        /// </summary>
        /// <param name="coefficient">The coefficient.</param>
        /// <returns>The step.</returns>
        public static decimal GetStep(decimal coefficient)
        {
            decimal[] borders = { 0M, 1M, 2M, 3M, 4M, 6M, 10M, 20M, 30M, 50M, 100M, 1000M };
            decimal[] steps = { 0M, 0.01M, 0.02M, 0.05M, 0.1M, 0.2M, 0.5M, 1M, 2M, 5M, 10M };

            for (int i = 0; i < borders.Length - 1; ++i)
            {
                if (coefficient >= borders[i] && coefficient < borders[i + 1])
                {
                    return steps[i];
                }
            }

            if (coefficient == borders[borders.Length - 1])
            {
                return steps[steps.Length - 1];
            }

            throw new ArgumentException(String.Format("Coefficient {0} does not exist in our case.", coefficient));
        }

        /// <summary>
        /// Converts the given market to the record to write it to series-file.
        /// </summary>
        /// <param name="market">Market for the conversion.</param>
        /// <returns>The record.</returns>
        public static string CreateRecord(Market market)
        {
            //Table table = new Table(Global.Instance.GetOdds(market.MarketId));
            Table table = new TableDao().GetTable(market.MarketId);

            return String.Format("{0} {1} {2}{3}"
                , table.InPair.ToString().Replace(',', '.')
                , table.AsLine.Replace(',', '.')
                , market.EventDateMs - Utils.Now
                , Environment.NewLine);
        }

        /// <summary>
        /// For the given sport event calculates how frequently each market name is met.
        /// </summary>
        /// <param name="sportEventId">Sport event identifier.</param>
        /// <returns>Name-frequency pairs for each market name of given sport event.</returns>
        public static Dictionary<String, Int32> CalculateMarketsFrequencies(int sportEventId)
        {
            List<Market> cells = Global.Instance.GetMarkets(sportEventId, DateTime.UtcNow.Date, DateTime.UtcNow.Date.AddDays(2));
            Dictionary<String, Int32> names = new Dictionary<string, int>();

            foreach (Market market in cells)
            {
                names = Add(names, market.MarketName);
            }

            // sort the dictionary by the value
            names = Sort(names);

            return names;
        }

        /// <summary>
        /// Prints the dictionary.
        /// </summary>
        /// <param name="dictionary">Dictionary to print.</param>
        public static void PrintDictionary(Dictionary<String, Int32> dictionary)
        {
            Int32 value;

            foreach (String name in dictionary.Keys)
            {
                dictionary.TryGetValue(name, out value);
                Console.WriteLine(name + " [" + value + "]");
            }
        }

        private static Dictionary<String, Int32> Add(Dictionary<String, Int32> dictionary, String element)
        {
            int value;

            if (dictionary.TryGetValue(element, out value))
            {
                dictionary.Remove(element);
                dictionary.Add(element, value + 1);
            }
            else
            {
                dictionary.Add(element, 1);
            }

            return dictionary;
        }

        private static Dictionary<String, Int32> Sort(Dictionary<String, Int32> dictionary)
        {
            return (from entry in dictionary orderby entry.Value descending select entry)
                .ToDictionary(pair => pair.Key, pair => pair.Value);
        }
    }
}
